/*
 *
 * Saturn Framework Co.Limt
 * Copyright (c) 2012-2019 tanks, Inc. All rights reserved.
 */

package com.saturn.config.server.web;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.saturn.config.server.base.R;
import com.saturn.config.server.base.dto.JsonResult;
import com.saturn.config.server.base.entity.AppConfig;
import com.saturn.config.server.base.entity.AppInfo;
import com.saturn.config.server.service.AppConfigService;
import com.saturn.config.server.service.AppInfoService;
import com.saturn.config.server.util.YamlPropUtil;

import cn.hutool.core.util.NetUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <dl>
 * <dt><b>Title:</b></dt>
 * <dd>none</dd>
 * <dt><b>Description:</b></dt>
 * <dd>
 * <p>
 * 应用信息表</dd>
 *
 * @author tanks
 * @date 2019-07-08 14:50:16
 */
@Slf4j
@Controller
@RequestMapping("/appinfo")
@SuppressWarnings({ "rawtypes", "unchecked" })
public class AppInfoController {

	@Autowired
	private AppInfoService appInfoService;
	@Autowired
	private AppConfigService appConfigService;
	@Value("${app.sign.privite.key:6e776f703868396a7370773131307077}")
	private String priKey;
	
	/**
	 * 分页查询
	 * 
	 * @param page    分页对象
	 * @param appInfo 应用信息表
	 * @return
	 */

	@RequestMapping(value = "/page", produces = "application/json")
	public @ResponseBody IPage<?> getAppInfoPage(HttpServletRequest request, Page page, AppInfo appInfo) {
		String start = request.getParameter("start");
		String limit = request.getParameter("limit");
		if (StringUtils.isBlank(start)) {
			page.setCurrent(Long.parseLong(start));
		} else {
			page.setCurrent(1l);
		}
		if (StringUtils.isBlank(limit)) {
			page.setSize(Long.parseLong(limit));
		} else {
			page.setSize(20l);
		}
		if( StringUtils.EMPTY.equals(appInfo.getMemo()) ) {
			appInfo.setMemo(null);
		}
		if( StringUtils.EMPTY.equals(appInfo.getEnvType()) ) {
			appInfo.setEnvType(null);
		}
		if( StringUtils.EMPTY.equals(appInfo.getAppId()) ) {
			appInfo.setAppId(null);
		}
		if( StringUtils.EMPTY.equals(appInfo.getAppName()) ) {
			appInfo.setAppName(null);
		}
		
		return appInfoService.page(page, Wrappers.query(appInfo));
	}

	
	/**
	 * 添加应用，可以从其他应用复制
	 * @param basicInfo
	 * @param result
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/saveAddApplication", method = RequestMethod.POST)
	public @ResponseBody R saveAddApplication(@Valid AppInfo appInfo,BindingResult result,HttpServletResponse response) throws IOException{
		R<?> jsonResult = new R();
		if( "on".equals(appInfo.getIsPublic()) ) {
			appInfo.setIsPublic("1");
		}else {
			appInfo.setIsPublic("0");
		}
		if( "on".equals(appInfo.getIncludePublic()) ) {
			appInfo.setIncludePublic("1");
		}else {
			appInfo.setIncludePublic("0");
		}
		appInfo.setCreateTime(LocalDateTime.now());
		int i = appInfoService.saveAddApplication(appInfo);
		if(i == 1){
			jsonResult.setSuccess(Boolean.TRUE.booleanValue());
			jsonResult.setMsg("添加项目成功！");
		}else if(i == -1){
			jsonResult.setSuccess(Boolean.FALSE.booleanValue());
			jsonResult.setMsg("配置Key["+ appInfo.getAppName() +"]已存在！");
		}else{
			jsonResult.setSuccess(Boolean.FALSE.booleanValue());
			jsonResult.setMsg("新增应用出错！");
		}
		return jsonResult;
	}
	
	/** 
	 * 批量保存项目信息
	 * @param request
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "batchSaveApplications",produces="application/json")
	public @ResponseBody JsonResult batchSaveApplications(HttpServletRequest request) {
		JsonResult response = new JsonResult();
		String jsonText = request.getParameter("datas");
		List<AppInfo> appInfos = JSONObject.parseArray(jsonText, AppInfo.class);
		int count = this.appInfoService.batchSaveApplications(appInfos);
		if( count>0 ){
			response.setSuccess(Boolean.TRUE.booleanValue());
			response.setRespMsg("保存数据成功，更新记录数【" + count + "】条！");
		}else{
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("应用重名，保存修改数据失败！");
		}
		return response;
	}
	
	/**
	 * 批量项目配置
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "/deleteApplications",method = RequestMethod.POST,produces="application/json")
	public @ResponseBody JsonResult deleteApplications(@RequestParam("appIds") String[] appIds) {
		JsonResult response = new JsonResult();
		if( appIds==null || appIds.length==0 ){
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("删除失败！");
		}
		try{
			int size = this.appInfoService.deleteApplications(appIds);
			if( size>0 ){
				response.setSuccess(Boolean.TRUE.booleanValue());
				response.setRespMsg("删除成功,总共" + size + "个应用！");
			}else{
				response.setSuccess(Boolean.FALSE.booleanValue());
				response.setRespMsg("删除失败！");
			}
		}catch(Exception ex){
			log.error("失败",ex);
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("删除失败");
		}
		return response;
	}
	
	/**
	 * 批量生成URL地址
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "/genAppliationUrl",method = RequestMethod.POST,produces="application/json")
	public @ResponseBody JsonResult genAppliationUrl(HttpServletRequest request,@RequestParam("appIds") String[] appIds) {
		JsonResult response = new JsonResult();
		if( appIds==null || appIds.length==0 ){
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("删除失败！");
		}
		try{
			String serverUrl = "http://" + NetUtil.getLocalhostStr() + ":" + request.getServerPort() + "/" + request.getContextPath() + "api/queryAppInfo.htm?"; 
			String content = this.appInfoService.genAppliationUrl(serverUrl,this.priKey,appIds);
			response.setSuccess(Boolean.TRUE.booleanValue());
			response.setRespMsg(content);
		}catch(Exception ex){
			log.error("失败",ex);
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("删除失败");
		}
		return response;
	}
	
	/**
	 * 升级项目版本，版本一次递增
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "/upgradeApplication",method = RequestMethod.POST,produces="application/json")
	public @ResponseBody JsonResult upgradeApplication(@RequestParam("appId") String appId) {
		JsonResult response = new JsonResult();
		if( StringUtils.isBlank(appId) ){
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("AppId参数不能为空，无法升级！");
			return response;
		}
		try{
			boolean success = this.appInfoService.upgradeApplication(appId);
			if( success ){
				response.setSuccess(Boolean.TRUE.booleanValue());
				response.setRespMsg("版本升级成功！");
			}else{
				response.setSuccess(Boolean.FALSE.booleanValue());
				response.setRespMsg("版本升级失败！");
			}
		}catch(Exception ex){
			log.error("失败",ex);
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("版本升级失败！");
		}
		return response;
	}
	
	/**
	 * 升级项目版本，版本一次递增
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "/downgradeApplication",method = RequestMethod.POST,produces="application/json")
	public @ResponseBody JsonResult downgradeApplication(@RequestParam("appId") String appId) {
		JsonResult response = new JsonResult();
		if( StringUtils.isBlank(appId) ){
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("AppId参数不能为空，无法降级版本！");
			return response;
		}
		try{
			boolean success = this.appInfoService.downgradeApplication(appId);
			if( success ){
				response.setSuccess(Boolean.TRUE.booleanValue());
				response.setRespMsg("版本降级成功！");
			}else{
				response.setSuccess(Boolean.FALSE.booleanValue());
				response.setRespMsg("版本降级失败！");
			}
		}catch(Exception ex){
			log.error("失败",ex);
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("版本降级失败！");
		}
		return response;
	}
	
	/** 
	 * 导出应用配置项
	 * @param request
	 * @return
	 * @throws IOException 
	 * @throws BusinessException
	 */
	@RequestMapping(value = "exportApplications")
	public void exportApplications(HttpServletRequest request,HttpServletResponse response,String ids,String type) throws IOException {
		if( StringUtils.isBlank(ids) ) return;
		response.setContentType("application/octet-stream");
		// 设置导出Excel的名称
		response.setHeader("Content-disposition", "attachment;filename=" + new String(("yml".equals(type) ? "config.yml":"config.properties").getBytes("GB2312"), "ISO_8859_1"));
		// 刷新缓冲
		response.flushBuffer();
		String[] appIds = ids.split(",");
		for(String appId:appIds) {
			AppInfo appInfo = this.appInfoService.getById(appId);
			if( appInfo==null ) continue;
			QueryWrapper queryWrapper = Wrappers.query();
			queryWrapper.in("app_id", appId);
			queryWrapper.eq("version", appInfo.getCurrentVersion());
			queryWrapper.orderByDesc("app_id","config_key");
			List<AppConfig> list = appConfigService.list(queryWrapper);
			//检查是否包含公共配置
			if( list!=null && list.size()>0 ) {
				if( "yml".equals(type) ) {
					Properties props = new Properties();
					for(AppConfig appConfig:list) {
						props.put(appConfig.getConfigKey(), appConfig.getConfigValue());
					}
					String text = YamlPropUtil.properties2Yaml(props);
					response.getOutputStream().write(text.getBytes());
				}else {
					String line = "\r\n";
					byte[] eqs = "=".getBytes();
					byte[] lineByte = line.getBytes();
					response.getOutputStream().write(("#" + appInfo.getAppName() + " " + appInfo.getDescription() + " Version=" + appInfo.getCurrentVersion()).getBytes());
					response.getOutputStream().write(lineByte);
					for(AppConfig appConfig:list) {
						response.getOutputStream().write(appConfig.getConfigKey().getBytes());
						response.getOutputStream().write(eqs);
						response.getOutputStream().write(appConfig.getConfigValue().getBytes());
						response.getOutputStream().write(lineByte);
					}
					response.getOutputStream().write(lineByte);
				}
			}
		}
	}

}
